package main

import (
	"Learngo/mooc/2_1_interface/retriever/mock"
	real2 "Learngo/mooc/2_1_interface/retriever/real"
	"fmt"
	"time"
)

type Retriever interface {
	Get1(url string) string
}

// Poster 我们再定义个Post方法
type Poster interface {
	Post(url string, form map[string]string) string
}

func download(r Retriever) string {
	return r.Get1("http://www.imooc.com")
}

func post(poster Poster) {
	poster.Post("http://www.imooc.com", map[string]string{
		"name":   "tang",
		"course": "golang",
	})
}

// RetrieverAndPoster 接口组合，定义一个同时拥有Retriever和Poster的方法
type RetrieverAndPoster interface {
	Retriever
	Poster
}

const url = "http://www.imooc.com"

func session(s RetrieverAndPoster) string {

	s.Post(url, map[string]string{
		"contents": "another faked contents",
	})
	return s.Get1(url)
}

func main() {
	var r Retriever
	retriever := &mock.Retriever{Contents: "this is a fake imooc.com"}
	r = retriever
	fmt.Printf("%T %v\n", r, r)
	inspect(r)

	r = &real2.Retriever{
		UserAgent: "Mozilla/5/0",
		TimeOut:   time.Minute,
	}
	fmt.Printf("%T %v\n", r, r)

	inspect(r)

	// Type assertion 类型断言

	if retriever, ok := r.(mock.Retriever); ok {
		fmt.Println(retriever.Contents)
	} else {
		fmt.Println("not a mock retriever")
	}

	fmt.Println("try a session!")
	//fmt.Println(download(r))
	fmt.Println(session(retriever))
}

func inspect(r Retriever) {
	fmt.Println("Inspecting", r)
	fmt.Printf(" > %T %v\n", r, r)
	fmt.Print(" > Type switch", r, r)
	switch v := r.(type) {
	case mock.Retriever:
		fmt.Println("Contents:", v.Contents)
	case *real2.Retriever:
		fmt.Println("Contents:", v.UserAgent)
	}
}
